package com.ruoyi.web.controller.ex;

import java.util.*;
import javax.servlet.http.HttpServletResponse;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.hutool.log.StaticLog;
import com.ruoyi.ex.domain.ExStudyReload;
import com.ruoyi.ex.service.IExQuestionService;
import com.ruoyi.ex.service.IExStudyReloadService;
import com.ruoyi.pv.domain.PvStudentRecord;
import com.ruoyi.pv.service.IPvStudentRecordService;
import com.ruoyi.pv.service.IPvTrainingClassService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.ex.domain.ExTestBank;
import com.ruoyi.ex.service.IExTestBankService;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.core.page.TableDataInfo;

/**
 * 自测题库Controller
 *
 * @author zzx
 * @date 2023-03-25
 */
@Api("自测题库")
@RestController
@RequestMapping("/ex/test_bank")
public class ExTestBankController extends BaseController {
    @Autowired private IExTestBankService exTestBankService;
    @Autowired private IExQuestionService exQuestionService;

//    /**
//     * 校验是否可以考试
//     * 1、报名了培训班
//     * 2、报名了考试
//     * 3、未参加过考试
//     */
//    @GetMapping("/check-ex")
//    @ApiOperation("校验是否可以考试")
//    public AjaxResult checkEx() {
//        Long userId = getUserId();
//        //查询今年是否已经预约
//        List<PvStudentRecord> pvStudentRecords = pvStudentRecordService.selectPvStudentRecordList(PvStudentRecord.builder().stuId(userId).build());
//        PvStudentRecord record;
//        if (ObjectUtil.isNotEmpty(pvStudentRecords)){
//            for (PvStudentRecord recordi : pvStudentRecords) {
//                if (DateUtil.thisYear() != DateTime.of(recordi.getCreateTime()).year()){
//                    return AjaxResult.error("您今年未有报名记录");
//                }else{
//                    record = recordi;
//                }
//            }
//        }
//        // 查询是否有考试报名记录
//        ExStudyReload build = ExStudyReload.builder().stuId(getUserId()).deptId(getDeptId()).build();
//        List<ExStudyReload> exStudyReloads = exStudyReloadService.selectExStudyReloadList(build);
//        if (ObjectUtil.isNotEmpty(exStudyReloads)){
//            ExStudyReload exStudyReload = exStudyReloads.get(0);
//            Integer status = exStudyReload.getStatus();
//            if (exStudyReload)
//        }else{
//            return AjaxResult.error("未查询到考试报名记录");
//        }
//    }

    /**
     * 查询自测题库列表
     */
    @GetMapping("/list")
    @ApiOperation("查询自测题库列表")
    public TableDataInfo list(ExTestBank exTestBank) {
        exTestBank.setUserId(getUserId());
        startPage();
        List<ExTestBank> list = exTestBankService.selectExTestBankList(exTestBank);
        return getDataTable(list);
    }

    /**
     * 导出自测题库列表
     */
    @PreAuthorize("@ss.hasPermi('ex:test_bank:export')")
    @Log(title = "自测题库", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, ExTestBank exTestBank) {
        exTestBank.setUserId(getUserId());
        List<ExTestBank> list = exTestBankService.selectExTestBankList(exTestBank);
        ExcelUtil<ExTestBank> util = new ExcelUtil<ExTestBank>(ExTestBank.class);
        util.exportExcel(response, list, "自测题库数据");
    }

    /**
     * 获取自测题库详细信息
     */
    @GetMapping(value = "/{id}")
    @ApiOperation("获取自测题库详细信息")
    public AjaxResult getInfo(@PathVariable("id") Long id) {
        //获取已回答列表
        JSONObject answers = exTestBankService.getAnswers(getUserId(), id);
        return success(exTestBankService.selectExTestBankById(id)).put("answers",answers);
    }

    /**
     * 保存答案列表到缓存
     */
    @PostMapping("/saveAnswers/{bankId}")
    @ApiOperation("保存答案列表到缓存")
    public AjaxResult saveAnswers(@PathVariable("bankId")Long bankId,@RequestBody JSONObject answers){
        try{
            exTestBankService.saveAnswers(getUserId(),bankId,answers);
            return AjaxResult.success("保存成功");
        }catch (Exception e){
            logger.error("",e);
            return AjaxResult.error("保存失败");
        }
    }

    /**
     * 从缓存中获取答案
     */
    @PostMapping("/getAnswers/{bankId}")
    @ApiOperation("保存答案列表到缓存")
    public AjaxResult getAnswers(@PathVariable("bankId")Long bankId){
        try{
            return AjaxResult.success(exTestBankService.getAnswers(getUserId(),bankId));
        }catch (Exception e){
            logger.error("",e);
            return AjaxResult.error("保存失败");
        }
    }

    /**
     * 新增预约自测题库
     */
    @Log(title = "新增预约自测题库", businessType = BusinessType.INSERT)
    @PostMapping("/appoint")
    @ApiOperation("新增预约自测题库")
    public AjaxResult addAppointTest(@RequestBody(required = false) ExTestBank exTestBank) {
        //先查询是否有未完成的题库
        ExTestBank build = ExTestBank.builder().userId(getUserId()).reservedOne("appoint").status(0).build();
        List<ExTestBank> exTestBanks = exTestBankService.selectExTestBankList(build);
        if (ObjectUtil.isNotEmpty(exTestBanks)){
            exTestBank = exTestBanks.get(0);
            //从缓存中获取已回答列表
            JSONObject answers = exTestBankService.getAnswers(getUserId(), exTestBank.getId());
            return AjaxResult.success().put("bean",exTestBank).put("answers",answers);
        }else if (ObjectUtil.isEmpty(exTestBank)){//说明是查询
            return AjaxResult.success().put("bean",null);
        }else if(ObjectUtil.isEmpty(exTestBank.getTotal())){
            return AjaxResult.success().put("bean",null);
        }
        //生成自测名称
        exTestBank.setName(getUser().getNickName()+"_"+ DateTime.now().toString("yyyy-MM-dd HH:mm"));
        exTestBank.setReservedOne("appoint");
        return add(exTestBank);
    }

    /**
     * 新增自测题库
     * sig: ratio按题库比例、average平均选择、optional自选
     */
    @Log(title = "自测题库", businessType = BusinessType.INSERT)
    @PostMapping
    @ApiOperation("新增自测题库")
    public AjaxResult add(@Validated @RequestBody ExTestBank exTestBank) {
        //分析用户需求
        String sig = exTestBank.getSig();//类型
        Integer total = exTestBank.getTotal();
        Map<Long, Integer> questionCheckeds = exTestBank.getQuestionCheckeds();//选择的题库以及数量
        Set<Long> bankIds = questionCheckeds.keySet();//选择基础题库id
        int size = bankIds.size();
        Map<Long,Integer> selectQuestions = new HashMap<>();//计算后的每张表需要查询的条数，将随机交给数据库
        if ("optional".equals(sig)){//自选
            //总数
            exTestBank.setTotal(questionCheckeds.values().stream().reduce(Integer::sum).orElse(0));
            selectQuestions.putAll(questionCheckeds);
        }else if ("ratio".equals(sig)){//按题库比例
            if (size>1){
                Map<Long,Integer> dbQuestions = new HashMap<>();
                //遍历题库条数
                Integer dbTotal = 0;
                for (Long bankId : bankIds) {
                    int count = exQuestionService.selectExQuestionTotalByBankId(bankId);
                    dbTotal += count;
                    dbQuestions.put(bankId,count);
                }
                //计算题目数量占比
                for (Long id : dbQuestions.keySet()) {
                    Integer count = dbQuestions.get(id);
                    Double ratio = Double.valueOf(NumberUtil.formatPercent(count * 1.0 / dbTotal, 3).replace("%", ""));
                    //计算题目数量
                    selectQuestions.put(id,NumberUtil.round(total * (ratio / 100),0).intValue());
                }
            }else{
                selectQuestions.put(bankIds.iterator().next(), total);
            }
        }else {//默认 平均选择
            if (size>1){
                Integer half =  total / size;
                for (Long bankId : bankIds) {
                    selectQuestions.put(bankId,half);
                }
                //如果有余数说明有多出，多出部分给第一个题库
                if (total % size != 0){
                    Long first = bankIds.iterator().next();
                    selectQuestions.put(first,selectQuestions.get(first)+(total % size));
                }
            }else{
                selectQuestions.put(bankIds.iterator().next(), total);
            }
        }
        exTestBank.setUserId(getUserId());
        //随机从题库中选择题目
        List<Long> questionIds = exQuestionService.randomGetIds(selectQuestions);
        exTestBank.setQuestionIds(questionIds.toString());
        exTestBank.setStatus(0);
        return success(exTestBankService.insertExTestBank(exTestBank)).put("bean",exTestBank);
    }

    /**
     * 修改自测题库
     */
    @Log(title = "自测题库", businessType = BusinessType.UPDATE)
    @PutMapping
    @ApiOperation("修改自测题库")
    public AjaxResult edit(@RequestBody ExTestBank exTestBank) {
        return toAjax(exTestBankService.updateExTestBank(exTestBank));
    }

    /**
     * 删除自测题库
     */
    @PreAuthorize("@ss.hasPermi('ex:test_bank:remove')")
    @Log(title = "自测题库", businessType = BusinessType.DELETE)
    @DeleteMapping("/{ids}")
    @ApiOperation("删除自测题库")
    public AjaxResult remove(@PathVariable Long[] ids) {
        return toAjax(exTestBankService.deleteExTestBankByIds(ids));
    }
}
